Passed
Pull Request — master (#45)
by
unknown
06:19
created

tooltip.js ➔ show   D

Complexity

Conditions 13

Size

Total Lines 75
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 43
dl 0
loc 75
rs 4.2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like tooltip.js ➔ show often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*!
2
  * Bootstrap tooltip.js v4.5.3 (https://getbootstrap.com/)
3
  * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
  */
6
(function (global, factory) {
7
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('popper.js'), require('./util.js')) :
8
  typeof define === 'function' && define.amd ? define(['jquery', 'popper.js', './util.js'], factory) :
0 ignored issues
show
Bug introduced by
The variable define seems to be never declared. If this is a global, consider adding a /** global: define */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
9
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global.jQuery, global.Popper, global.Util));
0 ignored issues
show
Best Practice introduced by
If you intend to check if the variable self is declared in the current environment, consider using typeof self === "undefined" instead. This is safe if the variable is not actually declared.
Loading history...
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
Bug introduced by
The variable globalThis seems to be never declared. If this is a global, consider adding a /** global: globalThis */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
10
}(this, (function ($, Popper, Util) { 'use strict';
11
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
14
  var $__default = /*#__PURE__*/_interopDefaultLegacy($);
15
  var Popper__default = /*#__PURE__*/_interopDefaultLegacy(Popper);
16
  var Util__default = /*#__PURE__*/_interopDefaultLegacy(Util);
17
18
  /**
19
   * --------------------------------------------------------------------------
20
   * Bootstrap (v4.5.3): tools/sanitizer.js
21
   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
22
   * --------------------------------------------------------------------------
23
   */
24
  var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href'];
25
  var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
26
  var DefaultWhitelist = {
27
    // Global attributes allowed on any supplied element below.
28
    '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
29
    a: ['target', 'href', 'title', 'rel'],
30
    area: [],
31
    b: [],
32
    br: [],
33
    col: [],
34
    code: [],
35
    div: [],
36
    em: [],
37
    hr: [],
38
    h1: [],
39
    h2: [],
40
    h3: [],
41
    h4: [],
42
    h5: [],
43
    h6: [],
44
    i: [],
45
    img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
46
    li: [],
47
    ol: [],
48
    p: [],
49
    pre: [],
50
    s: [],
51
    small: [],
52
    span: [],
53
    sub: [],
54
    sup: [],
55
    strong: [],
56
    u: [],
57
    ul: []
58
  };
59
  /**
60
   * A pattern that recognizes a commonly useful subset of URLs that are safe.
61
   *
62
   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
63
   */
64
65
  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi;
66
  /**
67
   * A pattern that matches safe data URLs. Only matches image, video and audio types.
68
   *
69
   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
70
   */
71
72
  var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;
73
74
  function allowedAttribute(attr, allowedAttributeList) {
75
    var attrName = attr.nodeName.toLowerCase();
76
77
    if (allowedAttributeList.indexOf(attrName) !== -1) {
78
      if (uriAttrs.indexOf(attrName) !== -1) {
79
        return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN));
80
      }
81
82
      return true;
83
    }
84
85
    var regExp = allowedAttributeList.filter(function (attrRegex) {
86
      return attrRegex instanceof RegExp;
87
    }); // Check if a regular expression validates the attribute.
88
89
    for (var i = 0, len = regExp.length; i < len; i++) {
90
      if (attrName.match(regExp[i])) {
91
        return true;
92
      }
93
    }
94
95
    return false;
96
  }
97
98
  function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
99
    if (unsafeHtml.length === 0) {
100
      return unsafeHtml;
101
    }
102
103
    if (sanitizeFn && typeof sanitizeFn === 'function') {
104
      return sanitizeFn(unsafeHtml);
105
    }
106
107
    var domParser = new window.DOMParser();
108
    var createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');
109
    var whitelistKeys = Object.keys(whiteList);
110
    var elements = [].slice.call(createdDocument.body.querySelectorAll('*'));
111
112
    var _loop = function _loop(i, len) {
0 ignored issues
show
Unused Code introduced by
The parameter len is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
113
      var el = elements[i];
114
      var elName = el.nodeName.toLowerCase();
115
116
      if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) {
117
        el.parentNode.removeChild(el);
118
        return "continue";
119
      }
120
121
      var attributeList = [].slice.call(el.attributes);
122
      var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []);
123
      attributeList.forEach(function (attr) {
124
        if (!allowedAttribute(attr, whitelistedAttributes)) {
125
          el.removeAttribute(attr.nodeName);
126
        }
127
      });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
128
    };
129
130
    for (var i = 0, len = elements.length; i < len; i++) {
131
      var _ret = _loop(i);
132
133
      if (_ret === "continue") continue;
0 ignored issues
show
Unused Code introduced by
This continue has no effect on the loop flow and can be removed.
Loading history...
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
134
    }
135
136
    return createdDocument.body.innerHTML;
137
  }
138
139
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
0 ignored issues
show
Comprehensibility introduced by
It seems like you are trying to overwrite a function name here. _extends is already defined in line 139 as a function. While this will work, it can be very confusing.
Loading history...
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
140
141
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
142
143
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
144
  /**
145
   * ------------------------------------------------------------------------
146
   * Constants
147
   * ------------------------------------------------------------------------
148
   */
149
150
  var NAME = 'tooltip';
151
  var VERSION = '4.5.3';
152
  var DATA_KEY = 'bs.tooltip';
153
  var EVENT_KEY = "." + DATA_KEY;
154
  var JQUERY_NO_CONFLICT = $__default['default'].fn[NAME];
155
  var CLASS_PREFIX = 'bs-tooltip';
156
  var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g');
157
  var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'];
158
  var DefaultType = {
159
    animation: 'boolean',
160
    template: 'string',
161
    title: '(string|element|function)',
162
    trigger: 'string',
163
    delay: '(number|object)',
164
    html: 'boolean',
165
    selector: '(string|boolean)',
166
    placement: '(string|function)',
167
    offset: '(number|string|function)',
168
    container: '(string|element|boolean)',
169
    fallbackPlacement: '(string|array)',
170
    boundary: '(string|element)',
171
    sanitize: 'boolean',
172
    sanitizeFn: '(null|function)',
173
    whiteList: 'object',
174
    popperConfig: '(null|object)'
175
  };
176
  var AttachmentMap = {
177
    AUTO: 'auto',
178
    TOP: 'top',
179
    RIGHT: 'right',
180
    BOTTOM: 'bottom',
181
    LEFT: 'left'
182
  };
183
  var Default = {
184
    animation: true,
185
    template: '<div class="tooltip" role="tooltip">' + '<div class="arrow"></div>' + '<div class="tooltip-inner"></div></div>',
186
    trigger: 'hover focus',
187
    title: '',
188
    delay: 0,
189
    html: false,
190
    selector: false,
191
    placement: 'top',
192
    offset: 0,
193
    container: false,
194
    fallbackPlacement: 'flip',
195
    boundary: 'scrollParent',
196
    sanitize: true,
197
    sanitizeFn: null,
198
    whiteList: DefaultWhitelist,
199
    popperConfig: null
200
  };
201
  var HOVER_STATE_SHOW = 'show';
202
  var HOVER_STATE_OUT = 'out';
203
  var Event = {
204
    HIDE: "hide" + EVENT_KEY,
205
    HIDDEN: "hidden" + EVENT_KEY,
206
    SHOW: "show" + EVENT_KEY,
207
    SHOWN: "shown" + EVENT_KEY,
208
    INSERTED: "inserted" + EVENT_KEY,
209
    CLICK: "click" + EVENT_KEY,
210
    FOCUSIN: "focusin" + EVENT_KEY,
211
    FOCUSOUT: "focusout" + EVENT_KEY,
212
    MOUSEENTER: "mouseenter" + EVENT_KEY,
213
    MOUSELEAVE: "mouseleave" + EVENT_KEY
214
  };
215
  var CLASS_NAME_FADE = 'fade';
216
  var CLASS_NAME_SHOW = 'show';
217
  var SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
218
  var SELECTOR_ARROW = '.arrow';
219
  var TRIGGER_HOVER = 'hover';
220
  var TRIGGER_FOCUS = 'focus';
221
  var TRIGGER_CLICK = 'click';
222
  var TRIGGER_MANUAL = 'manual';
223
  /**
224
   * ------------------------------------------------------------------------
225
   * Class Definition
226
   * ------------------------------------------------------------------------
227
   */
228
229
  var Tooltip = /*#__PURE__*/function () {
230
    function Tooltip(element, config) {
231
      if (typeof Popper__default['default'] === 'undefined') {
232
        throw new TypeError('Bootstrap\'s tooltips require Popper.js (https://popper.js.org/)');
233
      } // private
234
235
236
      this._isEnabled = true;
237
      this._timeout = 0;
238
      this._hoverState = '';
239
      this._activeTrigger = {};
240
      this._popper = null; // Protected
241
242
      this.element = element;
243
      this.config = this._getConfig(config);
244
      this.tip = null;
245
246
      this._setListeners();
247
    } // Getters
248
249
250
    var _proto = Tooltip.prototype;
251
252
    // Public
253
    _proto.enable = function enable() {
254
      this._isEnabled = true;
255
    };
256
257
    _proto.disable = function disable() {
258
      this._isEnabled = false;
259
    };
260
261
    _proto.toggleEnabled = function toggleEnabled() {
262
      this._isEnabled = !this._isEnabled;
263
    };
264
265
    _proto.toggle = function toggle(event) {
266
      if (!this._isEnabled) {
267
        return;
268
      }
269
270
      if (event) {
271
        var dataKey = this.constructor.DATA_KEY;
272
        var context = $__default['default'](event.currentTarget).data(dataKey);
273
274
        if (!context) {
275
          context = new this.constructor(event.currentTarget, this._getDelegateConfig());
276
          $__default['default'](event.currentTarget).data(dataKey, context);
277
        }
278
279
        context._activeTrigger.click = !context._activeTrigger.click;
280
281
        if (context._isWithActiveTrigger()) {
282
          context._enter(null, context);
283
        } else {
284
          context._leave(null, context);
285
        }
286
      } else {
287
        if ($__default['default'](this.getTipElement()).hasClass(CLASS_NAME_SHOW)) {
288
          this._leave(null, this);
289
290
          return;
291
        }
292
293
        this._enter(null, this);
294
      }
295
    };
296
297
    _proto.dispose = function dispose() {
298
      clearTimeout(this._timeout);
299
      $__default['default'].removeData(this.element, this.constructor.DATA_KEY);
300
      $__default['default'](this.element).off(this.constructor.EVENT_KEY);
301
      $__default['default'](this.element).closest('.modal').off('hide.bs.modal', this._hideModalHandler);
302
303
      if (this.tip) {
304
        $__default['default'](this.tip).remove();
305
      }
306
307
      this._isEnabled = null;
308
      this._timeout = null;
309
      this._hoverState = null;
310
      this._activeTrigger = null;
311
312
      if (this._popper) {
313
        this._popper.destroy();
314
      }
315
316
      this._popper = null;
317
      this.element = null;
318
      this.config = null;
319
      this.tip = null;
320
    };
321
322
    _proto.show = function show() {
323
      var _this = this;
324
325
      if ($__default['default'](this.element).css('display') === 'none') {
326
        throw new Error('Please use show on visible elements');
327
      }
328
329
      var showEvent = $__default['default'].Event(this.constructor.Event.SHOW);
330
331
      if (this.isWithContent() && this._isEnabled) {
332
        $__default['default'](this.element).trigger(showEvent);
333
        var shadowRoot = Util__default['default'].findShadowRoot(this.element);
334
        var isInTheDom = $__default['default'].contains(shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, this.element);
335
336
        if (showEvent.isDefaultPrevented() || !isInTheDom) {
337
          return;
338
        }
339
340
        var tip = this.getTipElement();
341
        var tipId = Util__default['default'].getUID(this.constructor.NAME);
342
        tip.setAttribute('id', tipId);
343
        this.element.setAttribute('aria-describedby', tipId);
344
        this.setContent();
345
346
        if (this.config.animation) {
347
          $__default['default'](tip).addClass(CLASS_NAME_FADE);
348
        }
349
350
        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
351
352
        var attachment = this._getAttachment(placement);
353
354
        this.addAttachmentClass(attachment);
355
356
        var container = this._getContainer();
357
358
        $__default['default'](tip).data(this.constructor.DATA_KEY, this);
359
360
        if (!$__default['default'].contains(this.element.ownerDocument.documentElement, this.tip)) {
361
          $__default['default'](tip).appendTo(container);
362
        }
363
364
        $__default['default'](this.element).trigger(this.constructor.Event.INSERTED);
365
        this._popper = new Popper__default['default'](this.element, tip, this._getPopperConfig(attachment));
366
        $__default['default'](tip).addClass(CLASS_NAME_SHOW); // If this is a touch-enabled device we add extra
367
        // empty mouseover listeners to the body's immediate children;
368
        // only needed because of broken event delegation on iOS
369
        // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
370
371
        if ('ontouchstart' in document.documentElement) {
372
          $__default['default'](document.body).children().on('mouseover', null, $__default['default'].noop);
373
        }
374
375
        var complete = function complete() {
376
          if (_this.config.animation) {
377
            _this._fixTransition();
378
          }
379
380
          var prevHoverState = _this._hoverState;
381
          _this._hoverState = null;
382
          $__default['default'](_this.element).trigger(_this.constructor.Event.SHOWN);
383
384
          if (prevHoverState === HOVER_STATE_OUT) {
385
            _this._leave(null, _this);
386
          }
387
        };
388
389
        if ($__default['default'](this.tip).hasClass(CLASS_NAME_FADE)) {
390
          var transitionDuration = Util__default['default'].getTransitionDurationFromElement(this.tip);
391
          $__default['default'](this.tip).one(Util__default['default'].TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
392
        } else {
393
          complete();
394
        }
395
      }
396
    };
397
398
    _proto.hide = function hide(callback) {
399
      var _this2 = this;
400
401
      var tip = this.getTipElement();
402
      var hideEvent = $__default['default'].Event(this.constructor.Event.HIDE);
403
404
      var complete = function complete() {
405
        if (_this2._hoverState !== HOVER_STATE_SHOW && tip.parentNode) {
406
          tip.parentNode.removeChild(tip);
407
        }
408
409
        _this2._cleanTipClass();
410
411
        _this2.element.removeAttribute('aria-describedby');
412
413
        $__default['default'](_this2.element).trigger(_this2.constructor.Event.HIDDEN);
414
415
        if (_this2._popper !== null) {
416
          _this2._popper.destroy();
417
        }
418
419
        if (callback) {
420
          callback();
421
        }
422
      };
423
424
      $__default['default'](this.element).trigger(hideEvent);
425
426
      if (hideEvent.isDefaultPrevented()) {
427
        return;
428
      }
429
430
      $__default['default'](tip).removeClass(CLASS_NAME_SHOW); // If this is a touch-enabled device we remove the extra
431
      // empty mouseover listeners we added for iOS support
432
433
      if ('ontouchstart' in document.documentElement) {
434
        $__default['default'](document.body).children().off('mouseover', null, $__default['default'].noop);
435
      }
436
437
      this._activeTrigger[TRIGGER_CLICK] = false;
438
      this._activeTrigger[TRIGGER_FOCUS] = false;
439
      this._activeTrigger[TRIGGER_HOVER] = false;
440
441
      if ($__default['default'](this.tip).hasClass(CLASS_NAME_FADE)) {
442
        var transitionDuration = Util__default['default'].getTransitionDurationFromElement(tip);
443
        $__default['default'](tip).one(Util__default['default'].TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
444
      } else {
445
        complete();
446
      }
447
448
      this._hoverState = '';
449
    };
450
451
    _proto.update = function update() {
452
      if (this._popper !== null) {
453
        this._popper.scheduleUpdate();
454
      }
455
    } // Protected
456
    ;
457
458
    _proto.isWithContent = function isWithContent() {
459
      return Boolean(this.getTitle());
460
    };
461
462
    _proto.addAttachmentClass = function addAttachmentClass(attachment) {
463
      $__default['default'](this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment);
464
    };
465
466
    _proto.getTipElement = function getTipElement() {
467
      this.tip = this.tip || $__default['default'](this.config.template)[0];
468
      return this.tip;
469
    };
470
471
    _proto.setContent = function setContent() {
472
      var tip = this.getTipElement();
473
      this.setElementContent($__default['default'](tip.querySelectorAll(SELECTOR_TOOLTIP_INNER)), this.getTitle());
474
      $__default['default'](tip).removeClass(CLASS_NAME_FADE + " " + CLASS_NAME_SHOW);
475
    };
476
477
    _proto.setElementContent = function setElementContent($element, content) {
478
      if (typeof content === 'object' && (content.nodeType || content.jquery)) {
479
        // Content is a DOM node or a jQuery
480
        if (this.config.html) {
481
          if (!$__default['default'](content).parent().is($element)) {
482
            $element.empty().append(content);
483
          }
484
        } else {
485
          $element.text($__default['default'](content).text());
486
        }
487
488
        return;
489
      }
490
491
      if (this.config.html) {
492
        if (this.config.sanitize) {
493
          content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn);
494
        }
495
496
        $element.html(content);
497
      } else {
498
        $element.text(content);
499
      }
500
    };
501
502
    _proto.getTitle = function getTitle() {
503
      var title = this.element.getAttribute('data-original-title');
504
505
      if (!title) {
506
        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
507
      }
508
509
      return title;
510
    } // Private
511
    ;
512
513
    _proto._getPopperConfig = function _getPopperConfig(attachment) {
514
      var _this3 = this;
515
516
      var defaultBsConfig = {
517
        placement: attachment,
518
        modifiers: {
519
          offset: this._getOffset(),
520
          flip: {
521
            behavior: this.config.fallbackPlacement
522
          },
523
          arrow: {
524
            element: SELECTOR_ARROW
525
          },
526
          preventOverflow: {
527
            boundariesElement: this.config.boundary
528
          }
529
        },
530
        onCreate: function onCreate(data) {
531
          if (data.originalPlacement !== data.placement) {
532
            _this3._handlePopperPlacementChange(data);
533
          }
534
        },
535
        onUpdate: function onUpdate(data) {
536
          return _this3._handlePopperPlacementChange(data);
537
        }
538
      };
539
      return _extends({}, defaultBsConfig, this.config.popperConfig);
540
    };
541
542
    _proto._getOffset = function _getOffset() {
543
      var _this4 = this;
544
545
      var offset = {};
546
547
      if (typeof this.config.offset === 'function') {
548
        offset.fn = function (data) {
549
          data.offsets = _extends({}, data.offsets, _this4.config.offset(data.offsets, _this4.element) || {});
550
          return data;
551
        };
552
      } else {
553
        offset.offset = this.config.offset;
554
      }
555
556
      return offset;
557
    };
558
559
    _proto._getContainer = function _getContainer() {
560
      if (this.config.container === false) {
561
        return document.body;
562
      }
563
564
      if (Util__default['default'].isElement(this.config.container)) {
565
        return $__default['default'](this.config.container);
566
      }
567
568
      return $__default['default'](document).find(this.config.container);
569
    };
570
571
    _proto._getAttachment = function _getAttachment(placement) {
572
      return AttachmentMap[placement.toUpperCase()];
573
    };
574
575
    _proto._setListeners = function _setListeners() {
576
      var _this5 = this;
577
578
      var triggers = this.config.trigger.split(' ');
579
      triggers.forEach(function (trigger) {
580
        if (trigger === 'click') {
581
          $__default['default'](_this5.element).on(_this5.constructor.Event.CLICK, _this5.config.selector, function (event) {
582
            return _this5.toggle(event);
583
          });
584
        } else if (trigger !== TRIGGER_MANUAL) {
585
          var eventIn = trigger === TRIGGER_HOVER ? _this5.constructor.Event.MOUSEENTER : _this5.constructor.Event.FOCUSIN;
586
          var eventOut = trigger === TRIGGER_HOVER ? _this5.constructor.Event.MOUSELEAVE : _this5.constructor.Event.FOCUSOUT;
587
          $__default['default'](_this5.element).on(eventIn, _this5.config.selector, function (event) {
588
            return _this5._enter(event);
589
          }).on(eventOut, _this5.config.selector, function (event) {
590
            return _this5._leave(event);
591
          });
592
        }
593
      });
594
595
      this._hideModalHandler = function () {
596
        if (_this5.element) {
597
          _this5.hide();
598
        }
599
      };
600
601
      $__default['default'](this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler);
602
603
      if (this.config.selector) {
604
        this.config = _extends({}, this.config, {
605
          trigger: 'manual',
606
          selector: ''
607
        });
608
      } else {
609
        this._fixTitle();
610
      }
611
    };
612
613
    _proto._fixTitle = function _fixTitle() {
614
      var titleType = typeof this.element.getAttribute('data-original-title');
615
616
      if (this.element.getAttribute('title') || titleType !== 'string') {
617
        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
618
        this.element.setAttribute('title', '');
619
      }
620
    };
621
622
    _proto._enter = function _enter(event, context) {
623
      var dataKey = this.constructor.DATA_KEY;
624
      context = context || $__default['default'](event.currentTarget).data(dataKey);
625
626
      if (!context) {
627
        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
628
        $__default['default'](event.currentTarget).data(dataKey, context);
629
      }
630
631
      if (event) {
632
        context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
633
      }
634
635
      if ($__default['default'](context.getTipElement()).hasClass(CLASS_NAME_SHOW) || context._hoverState === HOVER_STATE_SHOW) {
636
        context._hoverState = HOVER_STATE_SHOW;
637
        return;
638
      }
639
640
      clearTimeout(context._timeout);
641
      context._hoverState = HOVER_STATE_SHOW;
642
643
      if (!context.config.delay || !context.config.delay.show) {
644
        context.show();
645
        return;
646
      }
647
648
      context._timeout = setTimeout(function () {
649
        if (context._hoverState === HOVER_STATE_SHOW) {
650
          context.show();
651
        }
652
      }, context.config.delay.show);
653
    };
654
655
    _proto._leave = function _leave(event, context) {
656
      var dataKey = this.constructor.DATA_KEY;
657
      context = context || $__default['default'](event.currentTarget).data(dataKey);
658
659
      if (!context) {
660
        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
661
        $__default['default'](event.currentTarget).data(dataKey, context);
662
      }
663
664
      if (event) {
665
        context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = false;
666
      }
667
668
      if (context._isWithActiveTrigger()) {
669
        return;
670
      }
671
672
      clearTimeout(context._timeout);
673
      context._hoverState = HOVER_STATE_OUT;
674
675
      if (!context.config.delay || !context.config.delay.hide) {
676
        context.hide();
677
        return;
678
      }
679
680
      context._timeout = setTimeout(function () {
681
        if (context._hoverState === HOVER_STATE_OUT) {
682
          context.hide();
683
        }
684
      }, context.config.delay.hide);
685
    };
686
687
    _proto._isWithActiveTrigger = function _isWithActiveTrigger() {
688
      for (var trigger in this._activeTrigger) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
689
        if (this._activeTrigger[trigger]) {
690
          return true;
691
        }
692
      }
693
694
      return false;
695
    };
696
697
    _proto._getConfig = function _getConfig(config) {
698
      var dataAttributes = $__default['default'](this.element).data();
699
      Object.keys(dataAttributes).forEach(function (dataAttr) {
700
        if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) {
701
          delete dataAttributes[dataAttr];
702
        }
703
      });
704
      config = _extends({}, this.constructor.Default, dataAttributes, typeof config === 'object' && config ? config : {});
705
706
      if (typeof config.delay === 'number') {
707
        config.delay = {
708
          show: config.delay,
709
          hide: config.delay
710
        };
711
      }
712
713
      if (typeof config.title === 'number') {
714
        config.title = config.title.toString();
715
      }
716
717
      if (typeof config.content === 'number') {
718
        config.content = config.content.toString();
719
      }
720
721
      Util__default['default'].typeCheckConfig(NAME, config, this.constructor.DefaultType);
722
723
      if (config.sanitize) {
724
        config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn);
725
      }
726
727
      return config;
728
    };
729
730
    _proto._getDelegateConfig = function _getDelegateConfig() {
731
      var config = {};
732
733
      if (this.config) {
734
        for (var key in this.config) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
735
          if (this.constructor.Default[key] !== this.config[key]) {
736
            config[key] = this.config[key];
737
          }
738
        }
739
      }
740
741
      return config;
742
    };
743
744
    _proto._cleanTipClass = function _cleanTipClass() {
745
      var $tip = $__default['default'](this.getTipElement());
746
      var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
747
748
      if (tabClass !== null && tabClass.length) {
749
        $tip.removeClass(tabClass.join(''));
750
      }
751
    };
752
753
    _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) {
754
      this.tip = popperData.instance.popper;
755
756
      this._cleanTipClass();
757
758
      this.addAttachmentClass(this._getAttachment(popperData.placement));
759
    };
760
761
    _proto._fixTransition = function _fixTransition() {
762
      var tip = this.getTipElement();
763
      var initConfigAnimation = this.config.animation;
764
765
      if (tip.getAttribute('x-placement') !== null) {
766
        return;
767
      }
768
769
      $__default['default'](tip).removeClass(CLASS_NAME_FADE);
770
      this.config.animation = false;
771
      this.hide();
772
      this.show();
773
      this.config.animation = initConfigAnimation;
774
    } // Static
775
    ;
776
777
    Tooltip._jQueryInterface = function _jQueryInterface(config) {
778
      return this.each(function () {
779
        var $element = $__default['default'](this);
780
        var data = $element.data(DATA_KEY);
781
782
        var _config = typeof config === 'object' && config;
783
784
        if (!data && /dispose|hide/.test(config)) {
785
          return;
786
        }
787
788
        if (!data) {
789
          data = new Tooltip(this, _config);
790
          $element.data(DATA_KEY, data);
791
        }
792
793
        if (typeof config === 'string') {
794
          if (typeof data[config] === 'undefined') {
795
            throw new TypeError("No method named \"" + config + "\"");
796
          }
797
798
          data[config]();
799
        }
800
      });
801
    };
802
803
    _createClass(Tooltip, null, [{
804
      key: "VERSION",
805
      get: function get() {
806
        return VERSION;
807
      }
808
    }, {
809
      key: "Default",
810
      get: function get() {
811
        return Default;
812
      }
813
    }, {
814
      key: "NAME",
815
      get: function get() {
816
        return NAME;
817
      }
818
    }, {
819
      key: "DATA_KEY",
820
      get: function get() {
821
        return DATA_KEY;
822
      }
823
    }, {
824
      key: "Event",
825
      get: function get() {
826
        return Event;
827
      }
828
    }, {
829
      key: "EVENT_KEY",
830
      get: function get() {
831
        return EVENT_KEY;
832
      }
833
    }, {
834
      key: "DefaultType",
835
      get: function get() {
836
        return DefaultType;
837
      }
838
    }]);
839
840
    return Tooltip;
841
  }();
842
  /**
843
   * ------------------------------------------------------------------------
844
   * jQuery
845
   * ------------------------------------------------------------------------
846
   */
847
848
849
  $__default['default'].fn[NAME] = Tooltip._jQueryInterface;
850
  $__default['default'].fn[NAME].Constructor = Tooltip;
851
852
  $__default['default'].fn[NAME].noConflict = function () {
853
    $__default['default'].fn[NAME] = JQUERY_NO_CONFLICT;
854
    return Tooltip._jQueryInterface;
855
  };
856
857
  return Tooltip;
858
859
})));
860
//# sourceMappingURL=tooltip.js.map
861